//
//  CiotAPProvisioner.swift
//  casdon_swiftUI
//
//  Created by casdon on 2025/5/22.
//

import Foundation
import Combine
import Network

class CiotAPProvisioner: NSObject, ObservableObject {
    private var udpbroadcastReceiver = UDPBroadcastReceiver()
    private(set) var currentPeripheral: APPeripheral?
    private var isRightSSID = false // 当前连接的ssid是正确的ap热点
    weak var delegate: CiotManagerDelegate?
    
    func startListening(port: UInt16, handler: @escaping (String) -> Void)
    {
        udpbroadcastReceiver.setListeningPort(port)
        udpbroadcastReceiver.startListening {[weak self] message in
            // 解析
            if let jsonData = message.data(using: .utf8) {
                do {
                    print("udp receive message: \(jsonData)")
                    if let dictionary = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
                        self?.currentPeripheral = APPeripheral.parse(from: message)
                        handler(message)
                    }
                } catch {
                    print("Error parsing message json : \(error)")
                }
            }
        }
    }
    
    var timer: Timer?

    func startListenCurrentSSID(ssidPrifix: String) {
        timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) {[weak self] _ in
            if let ssid = PermissionManager.shared.getWiFiSSID() {
                if ssid.contains(ssidPrifix)
                {
                    // 检测到用户连接了正确的ap热点
                    self?.isRightSSID = true
                   let _ = self?.delegate?.scanResult(uuid: "", rspData: Data(), ssid: ssid, encrypted: false)
                    self?.stopTimer()
                }
            }
            
        }
    }

    // 停止定时器
    func stopTimer() {
        timer?.invalidate()
        timer = nil
    }
    
    func c_mobile_ap_scan_device(name: UnsafePointer<Int8>?) -> Ciot_res {
        // 扫描周围设备，由于iOS权限限制无法做到，所以由用户手动操作
        // TODO：name 为ap名称前缀，可以在此弹框提示用户连接哪个ap
        // 这里要 定时不断检测 用户连接的wifi名称ssid，当得到对应的ssid时 将传递给sdk层
        guard let cString = name else {
            return Ciot_Err
        }
        let swiftString = String(cString: cString)
        print("[Ciot DEBUG Mobile] c_mobile_ap_scan_device \(swiftString)")
        startListenCurrentSSID(ssidPrifix: swiftString)
        
        return Ciot_OK
    }
    
    func c_mobile_ap_connect(ssid: String, pass: String) -> Ciot_res {
        // 连接ap热点，用户手动操作
        return Ciot_OK
    }
    
    func c_mobile_ap_discovered_notify(name: String, pid: String, clinkStatus: Ciot_clink_connection_status, encrypted: Bool, password: String, random: Int32) -> Ciot_res {
        
        return Ciot_OK
    }

    func c_mobile_ap_udp_client_connect(port:Int32 ) -> Ciot_res
    {
        startListening(port: UInt16(port), handler: {_ in
            
        })
        return Ciot_OK
    }
    
    func c_mobile_ap_tcp_client_connect(ip: String, port: Int32) -> Ciot_res
    {
        return Ciot_OK
    }
    
    func c_mobile_ap_tcp_message_send(data: UnsafePointer<UInt8>?, len: Int) -> Ciot_res
    {
        return Ciot_OK
    }
}





//{"id":196,"pid":"uJOXYuLO","dt":4,"e":"ap_adv","t":1675641815563,"dv":{"ap_ip":"192.168.5.1","tcp_port":12345},"sign":"11c290f71d762f480f9e56e13f51e2b2296c3cd9879180d0ee64539f113201d2"}
// 主结构体
class APPeripheral: Codable {
    let id: Int
    let pid: String
    let dt: Int
    let event: String
    let timestamp: Int
    let deviceInfo: DeviceInfo
    let sign: String
    
    // 使用 CodingKeys 映射 JSON 键名
    private enum CodingKeys: String, CodingKey {
        case id
        case pid
        case dt
        case event = "e"
        case timestamp = "t"
        case deviceInfo = "dv"
        case sign
    }
    
    static func parse(from jsonString: String) -> APPeripheral? {
        guard let jsonData = jsonString.data(using: .utf8) else {
            print("无法将字符串转换为Data")
            return nil
        }
        
        do {
            let decoder = JSONDecoder()
            // 设置 key 的转换策略（将 snake_case 转为 camelCase）
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            return try decoder.decode(APPeripheral.self, from: jsonData)
        } catch {
            print("JSON 解析错误: \(error)")
            return nil
        }
    }
}

// 设备信息结构体
struct DeviceInfo: Codable {
    let apIp: String
    let tcpPort: Int
    
    private enum CodingKeys: String, CodingKey {
        case apIp = "ap_ip"
        case tcpPort = "tcp_port"
    }
}



class UDPBroadcastReceiver {
    private var listener: NWListener?
    private var connection: NWConnection?
    private var port: NWEndpoint.Port!
    
    func setListeningPort(_ port: UInt16)
    {
        self.port = NWEndpoint.Port(integerLiteral: port)
    }
    
    func startListening(handler: @escaping (String) -> Void) {
        if port == nil {
            print("port cannot is null")
            return
        }
        // 创建 UDP 监听器
        let parameters = NWParameters.udp
        parameters.allowFastOpen = true
        parameters.allowLocalEndpointReuse = true
        
        do {
            listener = try NWListener(using: parameters, on: port)
        } catch {
            print("Failed to create listener: \(error)")
            return
        }
        
        listener?.stateUpdateHandler = { state in
            switch state {
            case .ready:
                print("UDP listener ready on port \(String(describing: self.port))")
            case .failed(let error):
                print("Listener failed with error: \(error)")
                self.listener?.cancel()
            case .cancelled:
                print("Listener cancelled")
            default:
                break
            }
        }
        
        listener?.newConnectionHandler = { newConnection in
            self.connection = newConnection
            self.receiveData(connection: newConnection, handler: handler)
            newConnection.start(queue: .main)
        }
        
        listener?.start(queue: .main)
    }
    
    private func receiveData(connection: NWConnection, handler: @escaping (String) -> Void) {
        connection.receiveMessage { (data, context, isComplete, error) in
            if let data = data, !data.isEmpty {
                if let message = String(data: data, encoding: .utf8) {
                    print("Received message: \(message)")
                    handler(message)
                }
            }
            
            if let error = error {
                print("Receive error: \(error)")
                return
            }
            
            // 继续接收下一条消息
            self.receiveData(connection: connection, handler: handler)
        }
    }
    
    func stopListening() {
        listener?.cancel()
        connection?.cancel()
    }
}
